#region Using Statements
using System;
using System.IO;
using System.Xml.Linq;
using System.Threading;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Input.Touch;
using Microsoft.Xna.Framework.Media;

#endregion

namespace HOPE {
	/// <summary>
	/// This screen implements the actual game logic. It is just a
	/// placeholder to get the idea across: you'll probably want to
	/// put some more interesting gameplay in here!
	/// </summary>
	class Level0_1: Microsoft.Xna.Framework.Game {

		private GameScreen gameScreen;
		private ScreenManager screenManager;
		private TimeSpan timeSpan;

		private GameServiceContainer gameServiceContainer;


		#region Fields
		
		//resources for drawing
		private GraphicsDeviceManager _graphics;
		private SpriteBatch _spriteBatch;
		private GraphicsDevice _graphicsDevice;

		//meta level game state
		private LevelEngine level;
		private ContentManager _content;
		private int levelIndex = -1;
		private bool wasContinuePressed;

		//global content

		#region Fields(textures)
		private SpriteFont _menufont;

		private Texture2D _testpage;
		private Texture2D _playerpanel;

		//private Texture2D davinaaktif;
		//private Texture2D latifupasif;

		private Texture2D _audriannaaktif;
		private Texture2D _audriannapasif;
		private Texture2D _zakhaevaktif;
		private Texture2D _zakhaevpasif;

		private Texture2D pauseOverlay;
		private static bool IsPaused { get; set; }

		#endregion

		#region posisi
		
		Vector2 playerPosition = new Vector2(100, 100);
		//Vector2 enemyPosition = new Vector2(100, 100);

		Vector2 _testpagepos = new Vector2(0, 0);
		Vector2 _playerpanelpos = new Vector2(0, 0);

		//Vector2 davinaaktifpos = new Vector2(0, 0);
		//Vector2 davinapasifpos = new Vector2(0, 0);
		//Vector2 latifuaktifpos = new Vector2(0, 0);
		//Vector2 latifupasifpos = new Vector2(200, 0);
		Vector2 _zakhaevaktifpos = new Vector2(0, 0);
		Vector2 _zakhaevpasifpos = new Vector2(120, 0);
		Vector2 _audriannaaktifpos = new Vector2(0, 0);
		Vector2 _audriannapasifpos = new Vector2(200, 10);
		#endregion

		bool _isAudriannaAktif = false;
		bool _isZakhaevAktif = true;

		//Random random = new Random();

		// We store our input states so that we only poll once per frame, 
		// then we use the same input state wherever needed
		private GamePadState gamePadState;
		private KeyboardState keyboardState;
		private TouchCollection touchState;
		private DisplayOrientation displayOrientation;

		private const int numberOfLevels = 3;
		private const int BackBufferWidth = 800;
		private const int BackBufferHeight = 480;

		#region Fields(Virtual Pad)
		// a texture used to draw the Jump button on the screen
		public static Texture2D _jumpbutton;
		public static Vector2 _jumpbuttonpos = new Vector2(690, 370);
		public static bool _isJumpButtonClicked;

		// a texture used to draw the Jump button on the screen
		public static Texture2D _actionbutton;
		public static Vector2 _actionbuttonpos = new Vector2(610, 380);
		public static bool _isActionButtonClicked;
		public static bool _isActionButtonActive;

		// a texture used to draw the virtual thumbsticks on the screen
		public static Texture2D _controlstick;
		public static Texture2D _controlstickBoundary;
		public static Vector2 _controlstickpos = new Vector2(55, 369);
		public static Vector2 _controlstickBoundarypos = new Vector2(34, 347);
		#endregion

		//add viewport
		Viewport viewportHUD;
		Viewport viewportGameplay;

		#endregion

		#region Initialization


		/// <summary>
		/// Constructor.
		/// </summary>
		public Level0_1 () {

			_graphics = new GraphicsDeviceManager(this);

			//gameScreen.TransitionOffTime = TimeSpan.FromSeconds(1.5);
			//TimeSpan.TransitionOffTime = TimeSpan.FromSeconds(0.5);

			//gameScreen.EnabledGestures = GestureType.Tap;
			Content.RootDirectory = "Content";

			_graphics.IsFullScreen = true;
			//TargetElapsedTime = TimeSpan.FromTicks(333333);


		}

		/// <summary>
		/// LoadContent will be called once per game and is the place to load
		/// all of your content.
		/// </summary>
		protected override void LoadContent () {
			//if (_content == null)
			//    _content = new ContentManager(ScreenManager.Game.Services, "Content");


			_LoadAssets();

			// A real game would probably have more content than this sample, so
			// it would take longer to load. We simulate that by delaying for a
			// while, giving you a chance to admire the beautiful loading screen.
			Thread.Sleep(1000);

			// once the load has finished, we use ResetElapsedTime to tell the game's
			// timing mechanism that we have just finished a very long frame, and that
			// it should not try to catch up.
			screenManager.Game.ResetElapsedTime();

			base.LoadContent();
		}

		/// <summary>
		/// Unload graphics content used by the game.
		/// </summary>
		protected override void UnloadContent () {
			_content.Unload();
		}

		public void _LoadAssets () {
			// Loads the animation dictionary from an xml file
			//animations = new Dictionary<string, Animation>();
			//LoadAnimationFromXML();

			// Loads all textures that are required
			_LoadTextures();

			// Create all game components
			//CreateGameComponents();
		}

		#region private argument(load animation)
		//private void LoadAnimationFromXML()
		//{
		//    XDocument doc = XDocument.Load
		//        ("Content/Textures/AnimationDefinitions.xml");
		//    XName = XName.Get("Definition");
		//    var definitions = doc.Document.Descendants(name);

		//loop all definitons in the XML
		//    foreach (var animationDefinition in definitions)
		//    {
		//        // Get the name of the animation
		//        string animationAlias = animationDefinition.Attribute("Alias").Value;
		//        Texture2D texture =
		//            ScreenManager.Game.Content.Load<Texture2D>
		//            (animationDefinition.Attribute("SheetName").Value);

		//        // Get the frame size (width & height)
		//        Point frameSize = new Point();
		//        frameSize.X = int.Parse(
		//            animationDefinition.Attribute("FrameWidth").Value);
		//        frameSize.Y = int.Parse(
		//            animationDefinition.Attribute("FrameHeight").Value);

		//        // Get the frames sheet dimensions
		//        Point sheetSize = new Point();
		//        sheetSize.X = int.Parse(
		//            animationDefinition.Attribute("SheetColumns").Value);
		//        sheetSize.Y = int.Parse(
		//            animationDefinition.Attribute("SheetRows").Value);



		//        Animation animation = new Animation(texture, frameSize, sheetSize);

		//        // Checks for sub-animation definition
		//        if (animationDefinition.Element("SubDefinition") != null)
		//        {
		//            int startFrame = int.Parse(
		//                animationDefinition.Element("SubDefinition")
		//                .Attribute("StartFrame").Value);

		//            int endFrame = int.Parse
		//                (animationDefinition.Element("SubDefinition")
		//                .Attribute("EndFrame").Value);

		//            animation.SetSubAnimation(startFrame, endFrame);
		//        }

		//        if (animationDefinition.Attribute("Speed") != null)
		//        {
		//            animation.SetFrameInterval(
		//                TimeSpan.FromMilliseconds(
		//                double.Parse(animationDefinition.Attribute("Speed").Value)));
		//        }

		//        // If the definition has an offset defined - it should be  
		//        // rendered relative to some element/animation
		//        if (null != animationDefinition.Attribute("OffsetX") &&
		//            null != animationDefinition.Attribute("OffsetY"))
		//        {
		//            animation.Offset = new Vector2(int.Parse
		//                (animationDefinition.Attribute("OffsetX").Value),
		//                int.Parse(animationDefinition.Attribute("OffsetY").Value));
		//        }

		//        animations.Add(animationAlias, animation);
		//    }
		//}

		#endregion

		#region private argument(load textures)
		private void _LoadTextures () {
			//load overlay textures
			pauseOverlay = _content.Load<Texture2D>("Textures/MenuScreen/pauseoverlay");

			//load font
			_menufont = _content.Load<SpriteFont>("Textures/Interface/Fonts/menufont");

			//load background
			_testpage = _content.Load<Texture2D>("Textures/MenuScreen/pauseoverlay");

			//load inteface
			_playerpanel = _content.Load<Texture2D>("Textures/Interface/StatusBar/Panel/playerpanel");

			//char interface
			//davinaaktif = content.Load<Texture2D>("Textures/Interface/StatusBar/Player/Active/davinaaktif");
			//davinapasif = content.Load<Texture2D>("");
			//latifuaktif = content.Load<Texture2D>("");
			//latifupasif = content.Load<Texture2D>("Textures/Interface/StatusBar/Player/Passive/latifupasif");
			_zakhaevaktif = _content.Load<Texture2D>("Textures/Characters/Potrait/Active/zakhaevaktif");
			_zakhaevpasif = _content.Load<Texture2D>("Textures/Characters/Potrait/Passive/zakhaevpasif");
			_audriannaaktif = _content.Load<Texture2D>("Textures/Characters/Potrait/Active/audriannaaktif");
			_audriannapasif = _content.Load<Texture2D>("Textures/Characters/Potrait/Passive/audriannapasif");

			//load control
			_controlstick = _content.Load<Texture2D>("Textures/GamePlay/Control/controlstick");
			_controlstickBoundary = _content.Load<Texture2D>("Textures/Gameplay/Control/controlstickBoundary");
			_jumpbutton = _content.Load<Texture2D>("Textures/Gameplay/Control/jumpbutton");
			_actionbutton = _content.Load<Texture2D>("Textures/Gameplay/Control/actionbutton");

			//load theme song

			//Known issue that you get exceptions if you use Media PLayer while connected to your PC
			//See http://social.msdn.microsoft.com/Forums/en/windowsphone7series/thread/c8a243d2-d360-46b1-96bd-62b1ef268c66
			//Which means its impossible to test this from VS.
			//So we have to catch the exception and throw it away
			//try {
			//    MediaPlayer.IsRepeating = true;
			//    MediaPlayer.Play(Content.Load<Song>("Sounds/Music"));
			//}
			//catch { }

			//13. Initialize them like so.(Pass 2)
			viewportGameplay = new Viewport();//initializing VIEWPORT COVERING GAMEPLAY AREA ONLY
			viewportGameplay.X = 0;
			viewportGameplay.Y = 0;
			viewportGameplay.Width = BackBufferWidth;
			viewportGameplay.Height = (int)(BackBufferHeight / 1.3f);

			viewportHUD = new Viewport();//initializing FULLSCREEN VIEWPORT TO DRAW OUR ONSCREEN CONTROLS
			viewportHUD.X = 0;
			viewportHUD.Y = 0;
			viewportHUD.Width = BackBufferWidth;
			viewportHUD.Height = BackBufferHeight;

			LoadNextLevel();
		}

		
		#endregion

		#region private argument(create game components)
		private void CreateGameComponents () {
			//level = new Level(ScreenManager.Game);
			//ScreenManager.Game.Components.Add(level);
		}
		#endregion

		#endregion
		#region Update and Draw


		/// <summary>
		/// Allows the game to run logic such as updating the world,
		/// checking for collisions, gathering input, and playing audio.
		/// </summary>
		/// <param name="gameTime">Provides a snapshot of timing values.</param>
		protected override void Update (GameTime gameTime) {
			

			//update virtual thumbstick
			VirtualThumbsticks.Update();

			HandleThumbstick();

			//handle polling for our input and handling high-level input
			HandleInput();

			//update our level, passing down the gameTime along with all of our input states
			level.Update(gameTime, keyboardState, gamePadState, touchState, displayOrientation);


			//player up panel changger
			if (_isAudriannaAktif == true) {
				_audriannapasif = _audriannaaktif;
				_audriannapasifpos = _audriannaaktifpos;
				_isZakhaevAktif = false;
				_zakhaevaktif = _zakhaevpasif;
				_zakhaevaktifpos = _zakhaevpasifpos;
			}
			else {
				_audriannaaktif = _audriannapasif;
				_audriannaaktifpos = _audriannapasifpos;
				_isZakhaevAktif = true;
				_zakhaevpasif = _zakhaevaktif;
				_zakhaevpasifpos = _zakhaevaktifpos;
			}

			//if (isZakhaevAktif == true) {
			//    isAudriannaAktif = false;
			//}

			//base.Update(gameTime);

			//if (IsActive) {
				// Apply some random jitter to make the enemy move around.
				//const float randomization = 10;

				//enemyPosition.X += (float)(random.NextDouble() - 0.5) * randomization;
				//enemyPosition.Y += (float)(random.NextDouble() - 0.5) * randomization;

				// Apply a stabilizing force to stop the enemy moving off the screen.
				//Vector2 targetPosition = new Vector2(
				//    ScreenManager.GraphicsDevice.Viewport.Width / 2 - gameFont.MeasureString("Insert Gameplay Here").X / 2, 
				//    200);

				//enemyPosition = Vector2.Lerp(enemyPosition, targetPosition, 0.05f);

				// TODO: this game isn't very fun! You could probably improve
				// it by inserting something more interesting in this space :-)
			//}
		}

		private void HandleInput () {
			//get all of our input states
			keyboardState = Keyboard.GetState();
			gamePadState = GamePad.GetState(PlayerIndex.One);
			touchState = TouchPanel.GetState();

			//pause the game when bac is pressed
			if (gamePadState.Buttons.Back == ButtonState.Pressed)
				_spriteBatch.Draw(pauseOverlay, new Vector2(0, 0), Color.White);
			
			bool continuePressed =
				keyboardState.IsKeyDown(Keys.Space) ||
				gamePadState.IsButtonDown(Buttons.A) ||
				touchState.AnyTouch();

			//set our button is always reset to inactive state
			_isJumpButtonClicked = false;
			_isActionButtonClicked = false;

			// Perform the appropriate action to advance the game and
			// to get the player back to playing.
			if (!wasContinuePressed && continuePressed) {
				if (!level.Player.IsAlive) {
					level.StartNewLife();
				}
				else if (level.TimeRemaining == TimeSpan.Zero) {
					if (level.ReachedExit)
						LoadNextLevel();
					//else
					//    ReloadCurrentLevel();
				}
			}

			wasContinuePressed = continuePressed;

		}

		//6. Add Handle thumbstick method and call it from Update()
		//This method is responsible for animating onscreen Thumbstick
		private void HandleThumbstick () {
			//calculate the rectangle of the outer circle of the thumbstick
			Rectangle outerControlstick = new Rectangle(0, (int)_controlstickBoundarypos.Y - 35,
				_controlstickBoundary.Width + 60, _controlstickBoundary.Height + 60);
			
			//reset the thumbstick position when it's idle
			if (VirtualThumbsticks.LeftThumbstick == Vector2.Zero) {
				_controlstickpos = new Vector2(45, 399);
			}
			else {
				//moves the thumbstick's inner circle
				float radius = _controlstick.Width / 2 + 35;
				_controlstickpos = new Vector2(45, 339) + (VirtualThumbsticks.LeftThumbstick * radius / 2);
			}
		}

		private void LoadNextLevel () {
			//move to the next level
			levelIndex = (levelIndex + 1) % numberOfLevels;

			//unloads the content for the current level before loading the next one.
			if (level != null)
				level.Dispose();

			//load the level.
			string levelPath = string.Format("Content/Levels/Level0/level0_{0}.txt", levelIndex);
			using (Stream fileStream = TitleContainer.OpenStream(levelPath))
				level = new LevelEngine(gameServiceContainer, fileStream, levelIndex);

			
		}

		/// <summary>
		/// Draws the game from background to foreground.
		/// </summary>
		/// <param name="gameTime">Provides a snapshot of timing values.</param>
		protected override void Draw (GameTime gameTime) {
			// This game has a blue background. Why? Because!
			_graphics.GraphicsDevice.Clear(ClearOptions.Target,
											   Color.CornflowerBlue, 0, 0);

			//14. SET VIEWPORT TO DRAW YOUR GAMEPLAY SCREEN AREA FIRST
			_graphicsDevice.Viewport = viewportGameplay;

			level.Draw(gameTime, _spriteBatch); //Draw the level

			//15. RESET VIEWPORT TO COVER THE ENTIRE SCREEN AND DRAW YOUR HUD
			_graphicsDevice.Viewport = viewportHUD;


			//draw the GUI
			_spriteBatch.Begin();

			DrawActionButton();
			DrawJumpButton();
			_spriteBatch.Draw(_controlstickBoundary, _controlstickBoundarypos, Color.White);
			_spriteBatch.Draw(_controlstick, _controlstickpos, Color.White);

			_spriteBatch.End();

			DrawHud();

			base.Draw(gameTime);

			if (gameScreen.TransitionPosition > 0)
				screenManager.FadeBackBufferToBlack(1f - gameScreen.TransitionAlpha);
		}

		private void DrawJumpButton () {
			if (_isJumpButtonClicked)
			{
				_spriteBatch.Draw(_jumpbutton, new Rectangle((int)_jumpbuttonpos.X, 
					(int)_jumpbuttonpos.Y, 70, 70), new Rectangle(70, 0, 70, 70), 
					Color.White);
			}
			else{
				_spriteBatch.Draw(_jumpbutton, new Rectangle((int)_jumpbuttonpos.X,
					(int)_jumpbuttonpos.Y, 70, 70), new Rectangle(0, 0, 70, 70),
 					Color.White);
			}
		}

		private void DrawActionButton () {
			//ketika tidak ada sesuatu yang bisa mentrigger action button, dia akan mati
			if(_isActionButtonActive == true)
			{
				_spriteBatch.Draw(_actionbutton, _actionbuttonpos, Color.White);
			}
			else
			{
				_spriteBatch.Draw(_actionbutton, _actionbuttonpos, Color.Black);
			}

			if(_isActionButtonClicked)
			{
				_spriteBatch.Draw(_actionbutton, new Rectangle((int)_actionbuttonpos.X,
					(int)_actionbuttonpos.Y, 70, 70), new Rectangle(70, 0, 70, 70),
					Color.White);
			}
			else
			{
				_spriteBatch.Draw(_actionbutton, new Rectangle((int)_actionbuttonpos.X, 
					(int)_actionbuttonpos.Y, 70, 70), new Rectangle(0, 0, 70, 70),
					Color.White);
			}
		}

		private void DrawHud () {
			_spriteBatch.Begin();
			//back test
			_spriteBatch.Draw(_testpage, _testpagepos, null, Color.White, 0, new Vector2(0, 0), 1, SpriteEffects.None, 1);

			//draw panel 
			_spriteBatch.Draw(_playerpanel, _playerpanelpos, null, Color.White, 0, new Vector2(0, 0), 1, SpriteEffects.None, 0.99f);

			//player panel
			//spriteBatch.Draw(davinaaktif, davinaaktifpos, null, Color.White, 0, new Vector2(0, 0), new Vector2(0.8f, 0.8f), SpriteEffects.None, 0.96f);
			//spriteBatch.Draw(latifupasif, latifupasifpos, null, Color.White, 0, new Vector2(0, 0), new Vector2(0.8f, 0.8f), SpriteEffects.None, 0.95f);
			_spriteBatch.Draw(_zakhaevpasif, _zakhaevaktifpos, null, Color.White, 0, new Vector2(0, 0), 1, SpriteEffects.None, 0.92f);
			//spriteBatch.Draw(zakhaevpasif, zakhaevpasifpos, null, Color.White, 0, new Vector2(0, 0), new Vector2(0.6f, 0.6f), SpriteEffects.None, 0.94f);
			//spriteBatch.Draw(audriannapasif, audriannaaktifpos, null, Color.White, 0, new Vector2(0, 0), new Vector2(0.6f, 0.6f), SpriteEffects.None, 0.94f);
			_spriteBatch.Draw(_audriannapasif, _audriannapasifpos, null, Color.White, 0, new Vector2(0, 0), 1, SpriteEffects.None, 0.93f);
			_spriteBatch.End();
		}

		#endregion		
	}
}
